package net.goutalk.glcs.module.organization.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.YesOrNoEnum;
import net.goutalk.glcs.common.utils.RedisUtil;
import net.goutalk.glcs.module.organization.dto.UpdateUserPostDto;
import net.goutalk.glcs.module.organization.entity.Post;
import net.goutalk.glcs.module.organization.entity.UserDeptRelation;
import net.goutalk.glcs.module.organization.entity.UserPostRelation;
import net.goutalk.glcs.module.organization.mapper.UserPostRelationMapper;
import net.goutalk.glcs.module.organization.service.IUserDeptRelationService;
import net.goutalk.glcs.module.organization.service.IUserPostRelationService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class UserPostRelationServiceImpl extends ServiceImpl<UserPostRelationMapper, UserPostRelation> implements IUserPostRelationService {

    private final IUserDeptRelationService userDeptRelationService;

    private final RedisUtil redisUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addPostUser(UpdateUserPostDto dto) {
        Long postId = dto.getPostId();
        Long deptId = dto.getDeptId();
        //从缓存中获取岗位、用户岗位、用户部门信息数据
        List<Post> postList= redisUtil.get(GlobalConstant.POST_CACHE_KEY, new TypeReference<List<Post>>() {
        });
        List<UserDeptRelation> userDeptRelations= redisUtil.get(GlobalConstant.USER_DEPT_RELATION_CACHE_KEY, new TypeReference<List<UserDeptRelation>>() {
        });
        List<UserPostRelation> userPostRelations= redisUtil.get(GlobalConstant.USER_POST_RELATION_CACHE_KEY, new TypeReference<List<UserPostRelation>>() {
        });

        List<Long> userIds = new ArrayList<>();

        if (dto.getType() == YesOrNoEnum.NO.getCode()){
            userIds = dto.getUserIds();
        }else {
            //把该组织下所以的人员全部添加到岗位下面
            List<Long> deptIds = dto.getDepartmentIds();
            if (CollectionUtil.isNotEmpty(deptIds)){
                List<UserDeptRelation> list = userDeptRelations.stream().filter(x->deptIds.contains(x.getDeptId())).collect(Collectors.toList());
                //去重操作，防止一个用户在多个组织下
                userIds = list.stream().map(UserDeptRelation::getUserId).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
            }
        }

        List<UserPostRelation> userPostRelationList = new ArrayList<>(userIds.size());
        for (Long userId : userIds) {
            UserPostRelation userPostRelation = new UserPostRelation();
            userPostRelation.setPostId(postId);
            userPostRelation.setUserId(userId);
            userPostRelationList.add(userPostRelation);

        }

        //查询该岗位下的人员，用于删除对应人员的部门信息
        List<Long> userIdList = userPostRelations.stream().filter(x -> x.getPostId().equals(postId)).map(UserPostRelation::getUserId).collect(Collectors.toList());
        //先删除用户岗位关联表，岗位下存在的人员
        this.remove(Wrappers.<UserPostRelation>lambdaQuery().eq(UserPostRelation::getPostId, postId));
        //再保存用户岗位关联关系表数据
        this.saveBatch(userPostRelationList);
        //查询此岗位对应的部门，并将此岗位对应的部门删除
        Long deleteDeptId = postList.stream().filter(x->x.getId().equals(postId)).findFirst().orElse(new Post()).getDeptId();
        //删除对应的用户部门关联关系表数据
        List<UserDeptRelation> collect = userDeptRelations.stream().filter(x -> x.getDeptId().equals(deleteDeptId) && userIdList.contains(x.getUserId())).collect(Collectors.toList());
        userDeptRelationService.removeBatchByIds(collect);
        //如果部门下没有此人员，将此人员添加到该部门下
        List<UserDeptRelation> list = userDeptRelationService.list(Wrappers.<UserDeptRelation>query().lambda().eq(UserDeptRelation::getDeptId, deptId));
        List<UserDeptRelation> userDeptRelationList = new ArrayList<>();
        //需要被过滤掉的用户id
        List<Long> finalUserIds = userIds;
        List<Long> containList = list.stream().map(UserDeptRelation::getUserId).filter(u -> finalUserIds.contains(u)).collect(Collectors.toList());
        //拿userIds和userIdList的差集
        List<Long> subtractList = (List<Long>) CollectionUtil.subtract(userIds, containList);
        if (subtractList.size()>0){
            for (Long userId : subtractList) {
                UserDeptRelation userDeptRelation = new UserDeptRelation();
                userDeptRelation.setUserId(userId);
                userDeptRelation.setDeptId(deptId);
                userDeptRelationList.add(userDeptRelation);
            }
            userDeptRelationService.saveBatch(userDeptRelationList);
        }

        List<Long> finalUserIds1 = userIds;
        CompletableFuture.runAsync(() -> {
            List<UserPostRelation> userRelationList = this.list();
            redisUtil.set(GlobalConstant.USER_POST_RELATION_CACHE_KEY, userRelationList);

            List<UserDeptRelation> deptRelationList = userDeptRelationService.list();
            redisUtil.set(GlobalConstant.USER_DEPT_RELATION_CACHE_KEY, deptRelationList);
            // 清空用户单签选择岗位缓存，以及用户重新登录
            for (Long userId : finalUserIds1) {
                redisUtil.delete(GlobalConstant.LOGIN_IDENTITY_CACHE_PREFIX + userId);
                StpUtil.logout(userId);
            }
        });
        return Boolean.TRUE;
    }
}
